package org.theflex.ui.search{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	
	import mx.containers.FormItem;
	import mx.containers.ViewStack;
	import mx.controls.Label;
	import mx.controls.scrollClasses.ScrollBar;
	import mx.core.Application;
	import mx.core.Container;
	import mx.effects.Glow;
	import mx.events.EffectEvent;
	import mx.events.FlexEvent;
	
	import org.theflex.core.AutoScroll;
	
	public class UISearchManager{
		private static var _searchManager:UISearchManager;
		private var _detachEffect:Glow;
		private var _removeDetachEffect:Glow;
		private var _detachColor:uint;
		private var _oldResult:SearchResult;
		private var _searchAuthorizer:Function;
		
		public function UISearchManager(){
			_detachEffect = new Glow();
			_removeDetachEffect = new Glow();
			
			_detachEffect.blurXFrom = _detachEffect.blurYFrom = 0;
			_detachEffect.blurXTo = _detachEffect.blurYTo = 10;
			_detachEffect.alphaFrom = 0.8;
			_detachEffect.alphaTo = 0.8;
			_detachEffect.color = 0xFFFF00;
			_detachEffect.duration = 300;
			_detachEffect.inner = false;
			_detachEffect.strength = 10;
			_detachEffect.repeatCount = 1;
			
			_removeDetachEffect.blurXFrom = _removeDetachEffect.blurYFrom = 10;
			_removeDetachEffect.blurXTo = _removeDetachEffect.blurYTo = 0;
			_removeDetachEffect.alphaFrom = 0.8;
			_removeDetachEffect.alphaTo = 0.8;
			_removeDetachEffect.color = 0xFFFF00;
			_removeDetachEffect.duration = 300;
			_removeDetachEffect.inner = false;
			_removeDetachEffect.strength = 10;
			_removeDetachEffect.repeatCount = 1;
			
			_removeDetachEffect.addEventListener(EffectEvent.EFFECT_END, function(e:Event):void{
				_removeDetachEffect.target = null;
			});
		}
		
		public static function getInstance():UISearchManager{
			if(_searchManager == null){
				_searchManager = new UISearchManager();
			}
			
			return _searchManager;
		}
		
		public function clearResult():void{
			_oldResult = null;
		}
		
		public function set searchAuthorizer(f:Function):void{
			_searchAuthorizer = f;
		}
		
		public function get searchAuthorizer():Function{
			return _searchAuthorizer;
		}
		
		public function set detachColor(color:uint):void{
			_detachColor = color;
		}
		
		public function get detachColor():uint{
			return _detachColor;
		}
		
		public function find(text:String, ui:DisplayObject = null):void{
			if(ui == null){
				if(_oldResult != null){
					ui = _oldResult.foundUI;
				}else{
					ui = DisplayObject(Application.application);
				}
			}
			
			var result:SearchResult = doFind(text, ui);
			
			if(result != null){
				if(result.foundUI != null){
					_oldResult = result;
					show(result.foundUI); 
				}else if(result.containerToCreate != null){
					var c:Container = result.containerToCreate;
					
					c.addEventListener(FlexEvent.CREATION_COMPLETE, function(e:Event):void{
						find(text, c);
					});
					
					c.createComponentsFromDescriptors();
					c.invalidateDisplayList();					
				}
			}else{
				if( ! (ui is Application)){
					var parent:Container = ui.parent as Container;
					var nextIndex:int = parent.getChildIndex(ui) + 1; //Direção
					
					if(nextIndex < parent.numChildren){
						find(text, parent.getChildAt(nextIndex));
					}else{
						find(text, parent.parent);
					}
				}
			}
		}
		
		protected function doFind(text:String, ui:DisplayObject):SearchResult{
			if(_searchAuthorizer != null){
				if( ! _searchAuthorizer(ui) ){
					return null;
				}
			}
			
			var result:SearchResult = null;
			
			text = text.toUpperCase();
			
			if(ui is Container){
				var container:Container = ui as Container;
				
				if(container.numChildren == 0 && ! container.initialized){
					result = new SearchResult();
					result.containerToCreate = container;
					return result;
				}
				
				for each(var c:DisplayObject in container.getChildren()){
					result = doFind(text, c);
					
					if(result != null){
						if(_oldResult != null){
						 	if(_oldResult.foundUI != result.foundUI){
								return result;
							}
						}else{
							return result;
						}
					}
				}
			}
			
			if(ui is Label){
				var label:Label = ui as Label;
				
				if(label.text.toUpperCase().indexOf(text) > -1){
					result = new SearchResult();
					result.foundUI = label;
					
					if(_oldResult != null){
					 	if(_oldResult.foundUI != result.foundUI){
							return result;
						}
					}else{
						return result;
					}
				}
			}else if(ui is FormItem){
				var formItem:FormItem = ui as FormItem;
				
				if(formItem.label.toUpperCase().indexOf(text) > -1){
					result = new SearchResult();
					result.foundUI = formItem;
					
					if(_oldResult != null){
					 	if(_oldResult.foundUI != result.foundUI){
							return result;
						}
					}else{
						return result;
					}
				}
			}
			
			return null;
		}
		
		public function show(ui:DisplayObject, parent:DisplayObjectContainer = null):void{
			if(parent == null){
				parent = ui.parent;
			}
			
			AutoScroll.show(ui);
			
			while( ! (parent is Application)){
				if(parent is Container){
					var container:Container = parent as Container;
										
					if( ! container.visible){
						if(container.parent is ViewStack){
							var viewStack:ViewStack = container.parent as ViewStack;
							viewStack.selectedChild = container;
						}
					}
				}
				
				parent = parent.parent;
			}
			
			detach(ui);
		}
		
		public function detach(ui:DisplayObject):void{
			clearDetacheds();
			
			_detachEffect.target = ui;
			_detachEffect.play();
		}
		
		public function clearDetacheds():void{
			if(_detachEffect.target != null){
				_detachEffect.end();
				
				_removeDetachEffect.target = _detachEffect.target;
				_removeDetachEffect.play();
				_detachEffect.target = null;
			}
		}
	}
}